package com.apexedu.eas.util;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

/**
 * 
 * 【稳定版】<br/>
 * 【类名】：HttpRequest参数提取工具类<br/>
 * 【简介】：<br/>
 * 【依赖】：<br/>
 * 
 * @author SwordRays
 * @date 2013年6月3日 下午2:45:02
 * @since JDK1.6
 * @version 1.0.0
 *
 */
public class RequestUtil {
	/** ==========================普通================================== */
	/**
	 * 
	 * 【方法名】：获取请求的客户端信息-浏览器UserAgent<br/>
	 * 【简介】：<br/>
	 * 【创建时间】：2013年6月21日 上午1:13:46<br/>
	 * 
	 * @param request 请求对象
	 * @return 浏览器的UserAgent
	 */
	public static String getRequestClientBrowserUserAgent(HttpServletRequest request) {
		String result = null;
		if (null != request) {
			result = request.getHeader("User-Agent");
		}
		return result;
	}

	/**
	 * 
	 * 【方法名】：获取请求的客户端信息-访问设备<br/>
	 * 【简介】：<br/>
	 * 【创建时间】：2013年6月21日 上午1:18:04<br/>
	 * 
	 * @param request 请求对象
	 * @return 访问设备
	 */
	public static String getRequestClientDevice(HttpServletRequest request) {
		String result = null;
		if (null != request) {
			String userAgent = getRequestClientBrowserUserAgent(request);
			if (userAgent.contains("Android")) {
				result = "Android";
			} else if (userAgent.contains("iPhone")) {
				result = "iPhone";
			} else if (userAgent.contains("iPod")) {
				result = "iPod";
			} else if (userAgent.contains("iPad")) {
				result = "iPad";
			} else {
				result = "PC设备";
			}
		}
		return result;
	}

	/**
	 * 
	 * 【方法名】：获取请求的客户端信息-访问IP<br/>
	 * 【简介】：<br/>
	 * 【创建时间】：2013年6月21日 上午1:24:03<br/>
	 * 
	 * @param request 请求对象
	 * @return 访问IP
	 */
	@SuppressWarnings("rawtypes")
	public static String getRequestClientIP(HttpServletRequest request) {
		String result = null;
		if (null != request) {

			StringBuffer buf = new StringBuffer("all head info:\n");
			Enumeration enumeration = request.getHeaderNames();
			while (enumeration.hasMoreElements()) {
				Object head = enumeration.nextElement();
				if (null != head) {
					String value = request.getHeader(String.valueOf(head));
					buf.append(head + "=" + value + "\n");
				}
			}

			String ip = request.getHeader("x-forwarded-for");

			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("X-Forwarded-For");
			}

			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("Proxy-Client-IP");
			}

			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("WL-Proxy-Client-IP");
			}

			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("HTTP_CLIENT_IP");
			}

			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("HTTP_X_FORWARDED_FOR");
			}

			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getRemoteAddr();
			}

			if (null != ip && ip.indexOf(',') != -1) {
				// 如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串 IP 值
				// 取X-Forwarded-For中第一个非unknown的有效IP字符串
				// 如：X-Forwarded-For：192.168.1.110, 192.168.1.120, 192.168.1.130,
				// 192.168.1.100
				// 用户真实IP为： 192.168.1.110
				// 注意:当访问地址为 localhost 时 地址格式为 0:0:0:0:0:0:1
				System.out.println("ip=" + ip);
				String[] ips = ip.split(",");
				for (int i = 0; i < ips.length; i++) {
					if (null != ips[i] && !"unknown".equalsIgnoreCase(ips[i])) {
						ip = ips[i];
						break;
					}
				}
				if ("0:0:0:0:0:0:1".equals(ip)) {
					System.out.println("由于客户端访问地址使用 localhost，获取客户端真实IP地址错误，请使用IP方式访问");
				}
			}

			if ("unknown".equalsIgnoreCase(ip)) {
				System.out.println("由于客户端通过Squid反向代理软件访问，获取客户端真实IP地址错误，请更改squid.conf配置文件forwarded_for项默认是为on解决");
			}
			result = ip;
		}
		return result;
	}

	/**
	 * 
	 * 【方法名】：获取请求的协议（http|https）<br/>
	 * 【简介】：<br/>
	 * 【创建时间】：2013年6月3日 下午2:53:17<br/>
	 * 
	 * @param request 请求对象
	 * @return 协议字符串
	 */
	public static String getRequestScheme(HttpServletRequest request) {
		String result = null;
		if (null != request) {
			result = request.getScheme();
		}
		return result;
	}

	/**
	 * 
	 * 【方法名】：获取请求的服务器服务域名或ip<br/>
	 * 【简介】：<br/>
	 * 【创建时间】：2013年6月3日 下午2:53:45<br/>
	 * 
	 * @param request 请求对象
	 * @return 服务域名或ip
	 */
	public static String getRequestServerName(HttpServletRequest request) {
		String result = null;
		if (null != request) {
			result = request.getServerName();
		}
		return result;
	}

	/**
	 * 
	 * 【方法名】：获取请求的服务器服务端口<br/>
	 * 【简介】：<br/>
	 * 【创建时间】：2013年6月3日 下午2:54:04<br/>
	 * 
	 * @param request 请求对象
	 * @return 服务端口
	 */
	public static Integer getRequestServerPort(HttpServletRequest request) {
		Integer result = null;
		if (null != request) {
			result = request.getServerPort();
		}
		return result;
	}

	/**
	 * 
	 * 【方法名】：获取请求的内容映射路径（即项目的访问别名）<br/>
	 * 【简介】：<br/>
	 * 【创建时间】：2013年6月3日 下午2:54:24<br/>
	 * 
	 * @param request 请求对象
	 * @return web项目的访问别名
	 */
	public static String getRequestContextPath(HttpServletRequest request) {
		String result = null;
		if (null != request) {
			result = request.getContextPath();
		}
		return result;
	}

	/**
	 * 
	 * 【方法名】：获取服务器的基础服务路径（定位到当前项目）<br/>
	 * 【简介】：<br/>
	 * 【创建时间】：2013年6月3日 下午2:55:01<br/>
	 * 
	 * @param request 请求对象
	 * @return basepath
	 */
	public static String getBasePath(HttpServletRequest request) {
		String result = null;
		if (null != request) {
			String requestScheme = getRequestScheme(request);
			String requestServerName = getRequestServerName(request);
			Integer requestServerPort = getRequestServerPort(request);
			String requestContextPath = getRequestContextPath(request);
			result = requestScheme + "://" + requestServerName + ":" + requestServerPort + requestContextPath;
		}
		return result;
	}

	/**
	 * 
	 * 【方法名】：获取服务器的顶级服务路径<br/>
	 * 【简介】：从request中获取（定位到端口，与具体项目无关）。结果例如：https://localhost:8080<br/>
	 * 【创建时间】：2013年6月3日 下午2:56:15<br/>
	 * 
	 * @param request 请求对象
	 * @return rootpath
	 */
	public static String getRootPath(HttpServletRequest request) {
		String result = null;
		if (null != request) {
			String requestScheme = getRequestScheme(request);
			String requestServerName = getRequestServerName(request);
			Integer requestServerPort = getRequestServerPort(request);
			result = requestScheme + "://" + requestServerName + ":" + requestServerPort;
		}
		return result;
	}

	/**
	 * 
	 * 【方法名】：获取服务器的顶级服务路径<br/>
	 * 【简介】：从给定的basepath中截取。结果例如：https://localhost:8080<br/>
	 * 【创建时间】：2013年6月3日 下午3:07:21<br/>
	 * 
	 * @param basepath
	 * @return rootpath
	 */
	public static String getRootPath(String basepath) {
		String result = null;
		if (null != basepath && !"".equals(basepath.trim())) {
			String findStr = "://";
			Integer index = basepath.indexOf(findStr);
			String tempPath = basepath.substring(index + findStr.length());
			Integer endIndex = tempPath.indexOf("/");
			if (-1 == endIndex) {
				result = tempPath;
			} else {
				result = tempPath.substring(0, endIndex);
			}
			result = basepath.substring(0, index + findStr.length()) + result;
		}
		return result;
	}

	/** ==========================过滤相对路径,自动填充为绝对路径================================== */

	/**
	 * 
	 * 【方法名】：过滤相对路径，自动填充为绝对路径<br/>
	 * 【简介】：有两种类型，类型1是用rootPath填充，类型2是用basePath填充<br/>
	 * 【创建时间】：2013年6月3日 下午3:27:12<br/>
	 * 
	 * @param request 请求对象
	 * @param relativePath 相对路径字符串
	 * @param judgeType 判定类型(1:如果不以http或https开头则为相对路径；2:如果不以http、https或/开头则为相对路径)
	 * @param fillType 填充类型（1：针对系统填充rootPath；2：针对服务填充basePath）
	 * @return 处理好的绝对路径字符串
	 */
	public static String filterRelativePath2AbsolutePath(HttpServletRequest request, String relativePath, Integer judgeType, Integer fillType) {
		String result = null;
		if (null != relativePath && !"".equals(relativePath.trim())) {
			if (1 == judgeType) {
				if (!relativePath.startsWith("http://") && !relativePath.startsWith("https://")) {
					String startStr = null;
					if (1 == fillType) {
						startStr = getRootPath(request);
					} else if (2 == fillType) {
						startStr = getBasePath(request);
					}
					if (relativePath.startsWith("/")) {
						result = startStr + relativePath;
					} else {
						result = startStr + "/" + relativePath;
					}
				} else {
					result = relativePath;
				}
			} else if (2 == judgeType) {
				//TODO 没考虑好是否有这种必要
			} else {
				result = relativePath;
			}
		}
		return result;
	}

	/**
	 * 
	 * @see #filterRelativePath2AbsolutePath(HttpServletRequest, String, Integer)
	 * 
	 * @param request
	 * @param relativePath
	 * @return
	 */
	public static String filterRelativePath2AbsolutePathWithRootPath(HttpServletRequest request, String relativePath) {
		return filterRelativePath2AbsolutePath(request, relativePath, 1, 1);
	}

	/**
	 * 
	 * @see #filterRelativePath2AbsolutePath(HttpServletRequest, String, Integer)
	 * 
	 * @param request
	 * @param relativePath
	 * @return
	 */
	public static String filterRelativePath2AbsolutePathWithBasePath(HttpServletRequest request, String relativePath) {
		return filterRelativePath2AbsolutePath(request, relativePath, 1, 2);
	}

	/** ==========================ajax================================== */
	/**
	 * 
	 * 【方法名】：判定是否Ajax请求<br/>
	 * 【简介】：<br/>
	 * 【创建时间】：2013年6月3日 下午3:16:19<br/>
	 * 
	 * @param request 请求对象
	 * @return 判定结果（true|false）
	 */
	public static Boolean isAjaxRequest(HttpServletRequest request) {
		Boolean result = null;
		if (null != request) {
			String header = request.getHeader("X-Requested-With");
			result = "XMLHttpRequest".equalsIgnoreCase(header);
		} else {
			result = false;
		}
		return result;
	}

	/**
	 * 
	 * 【方法名】：判定是否Ajax请求<br/>
	 * 【简介】：<br/>
	 * 【创建时间】：2013年6月3日 下午3:17:12<br/>
	 * 
	 * @param header 请求对象中取出的header字符串
	 * @return 判定结果（true|false）
	 */
	public static Boolean isAjaxRequest(String header) {
		Boolean result = null;
		if (null != header && !"".equals(header.trim())) {
			result = "XMLHttpRequest".equalsIgnoreCase(header);
		}
		return result;
	}

	/** ==========================测试================================== */
	public static void main(String[] args) {
		String a = "http://thgenius.blog.51cto.com";
		System.out.println(getRootPath(a));
	}
}
